/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ejb.metier;

import com.ejb.persistence.Author;
import com.ejb.persistence.Book;
import com.ejb.persistence.BookCategory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Adel Boukelt
 * Class used to manage books
 * 
 */
@Stateless
public class BookManagerBean implements IBookManager {

    @PersistenceContext
    EntityManager em;

    /**
     * 
     * Return the ten most sold books
     * @param -
     * @return -
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Book> getMostSold()
    {
        List<Book> retour = new ArrayList<Book>();
        
        
        try {
            Query q = em.createNamedQuery("Invoice.findMostSoldBook");
            q.setMaxResults(10);
        
            List<Object[]> list = q.getResultList();       
            for (Object[] o: list){
                retour.add((Book)o[0]);
            }
            for(Book b:retour){
                em.refresh(b);
            }
           return retour;
        } catch (Exception e) {
            Book book = new Book();
            book.setTitle("Aucun produit n'a été encore vendu");
            retour.add(book);
            return retour;
        }
    }
    
    /**
     * 
     * Get books by category and keyword.
     * @param searchType use to determine if the user wana find books with category or only with the word, value can be: [key|category]
     * @param searchName the word(book) that the user wana find
     * @param category the category were the book were suppose to be
     * @return List<Book>retour, that is the list of books with all conditions user make
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Book> getBooks(String searchType, String searchName,  BookCategory category){
        List<Book> retour = null;
        try {
            if(searchName == ""){
                retour = getBooksByCategory(category);
            }
            else if("category".equals(searchType) && searchName!= ""){
                Query q = em.createNamedQuery("Book.findByCategKey");
                q.setParameter("key", "%"+searchName+"%");
                q.setParameter("category", category);
                retour = q.getResultList();
            }
            else if("key".equals(searchType)){
                Query q = em.createNamedQuery("Book.findByKey").setParameter("key", "%"+searchName+"%");
                retour = q.getResultList();
            }
            for(Book b:retour){
                em.refresh(b);
            }
            return retour;
        } catch (Exception e) {
            System.out.println("Le problème :"+e.getMessage());
            return null;
        }
    }
    
    /**
     * 
     * Return all books of the library
     * @param -
     * @return List<Book>retour, that is the list of all books
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Book> getAllBooks() {
        try {
            Query q = em.createNamedQuery("Book.findAll");
            List<Book> retour = q.getResultList();
            for(Book b:retour){
                em.refresh(b);
            }
            return retour;
        } catch (Exception e) {
            
            return null;
        }

    }
    
    /**
     * 
     * Return books of the category selected
     * @param category the category were books were suppose to be
     * @return List<Book>retour, that is the list of books of the same category
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Book> getBooksByCategory(BookCategory category) {
        try{

        Query q = em.createNamedQuery("Book.findByCategory");
        q.setParameter("category", category);
        List<Book> retour = q.getResultList();
        for(Book b:retour){
            em.refresh(b);
        }
        return retour;
        }  catch(Exception e){
            
            return null;
        }
    }
    
    /**
     * 
     * Return authors of one book
     * @param bookID the ID of the book user wana see
     * @return List<Author>retour, that is the list of authors for the book
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Author> getBookAuthors(Long bookId) {
        try {
            Book b = em.find(Book.class, bookId);
            List<Author> retour = b.getAuthors();
            for (Author a:retour){
                em.refresh(a);
            }
            return retour;
        } catch (Exception e) {
            return null;
        }
    } 
    
    /**
     * 
     * Return one book
     * @param bookID the ID of the book user wana see
     * @return Book, that is the book with the ID = bookId
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public Book getBookById(Long bookId) {
        try {
            Book b = em.find(Book.class, bookId);
            em.refresh(b);
            return b;
        } catch (Exception e) {
            return null;
        }

    }
    
    /**
     * 
     * Create a new book
     * @param title of the book
     * @param price 
     * @param stock
     * @param threshold 
     * @param cover
     * @param editor
     * @param publicationDate
     * @param summary
     * @param contents
     * @param available
     * @param authors List of authors ID
     * @param category
     * @return boolean
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public boolean insertBook(String title, float price, int stock, int threshold, String cover, String editor, Date publicationDate, String summary, String contents, boolean available, List<String> authorsId, BookCategory category) {
        try {
            Book book = new Book();
            book.setTitle(title);
            book.setPrice(price);
            book.setAvailable(available);
            book.setCategory(category);
            book.setContents(contents);
            book.setCover(cover);
            book.setEditor(editor);
            book.setPublicationDate(publicationDate);
            book.setStock(stock);
            book.setSummary(summary);
            book.setThreshold(threshold);

            em.persist(book);  

            for (String id:authorsId){
                Author a = em.find(Author.class, Long.parseLong(id));
                if (a.getBooks() == null){
                    a.setBooks(new ArrayList<Book>());
                }
                List<Book> books = a.getBooks();
                books.add(book);
                a.setBooks(books);

                em.persist(a);
            }         
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }
    
    /**
     * 
     * Update values of one book
     * @param book the book that must be updated
     * @return boolean
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public boolean updateBook(Book book, List<String> authorsId) {
        try {
            if (authorsId != null){
                System.out.println(authorsId);
                List<Author> authors = new ArrayList<Author>();
                
                //Remove the book from the old authors who are no longer in the list
                for (Author author:this.getAllAuthors()){
                    if(author.getBooks().contains(book) && !authorsId.contains(author.getId().toString())){
                        List<Book> b = author.getBooks();
                        b.remove(book);
                        author.setBooks(b);
                    }
                }
                
                
                for (String aId:authorsId){
                    Author a = em.find(Author.class, Long.parseLong(aId));
                    
                    if (a.getBooks() == null){
                        a.setBooks(new ArrayList<Book>());
                    }
                    if(!a.getBooks().contains(book)){
                        List<Book> books = a.getBooks();
                        books.add(book);
                        a.setBooks(books);
                    }

                    em.persist(a);
                    authors.add(a);

                    
                }
                book.setAuthors(authors);
            }
            
            em.merge(book);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    
    }
    
    /**
     * 
     * Return all the book that have their stock under the threshold
     * @param -
     * @return List<Book>
     * @see Book in com.ejb.metier
     * 
     */
    @Override
    public List<Book> getStockUnderThreshold(){
        try {
            Query q = em.createNamedQuery("Book.getStateStock");
            List<Book> retour = q.getResultList();
            return retour;
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 
     * Create a new author
     * @param firstName of the author
     * @param lastName
     * @return boolean
     * 
     */
    @Override
    public boolean createAuthors (String firstName, String lastName){
        
        try {
            Author author = new Author();
            author.setFirstName(firstName);
            author.setLastName(lastName);
            em.persist(author);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public List<Author> getAllAuthors() {
        try {
            Query q = em.createNamedQuery("Author.getAllAuthors");
            List<Author> retour = q.getResultList();
            return retour;
        } catch (Exception e) {
            return null;
        }
    }
    
    
}
